package server;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Encapsulates all necessary operations which have to be done which Auctions.
 * @author Andreas Mair
 */

public class UserManager 
{
	
	private static UserManager instance;
	
	private static Map<String,User> users;
	
	private UserManager()
	{
		users=new HashMap<String,User>();
	}
	
    public synchronized static UserManager getInstance() 
    {
        if(instance==null)
        {
        	instance=new UserManager();
        }
    	return instance;
    }
    
    
	/**
	 * Logs a User in (his ClientAddress will be set)
	 * @param strName User to log in
	 * @param iaClientAddress InetAddress of client
	 * @param iPClientPort int UDP-Port to send UDP-Messages to this User/Client
	 * @return User object or null if the user was already logged in (somewhere)
	 */
	public User login(String strName,InetAddress iaClientAddress,int iPClientPort)
	{
		User user=null;
		
		synchronized(this)
		{
			user=users.get(strName);
			if(user!=null && user.getIAClientAddress()!=null)
			{
				return null;
			}
			if(user==null)
			{
				user=new User(strName);
				users.put(strName, user);
			}
			user.setIAClientAddress(iaClientAddress);
			user.setiPClientPort(iPClientPort);
		}
		return user;
	}
	
	/**
	 * Sends Notifications to the user if it has some
	 * @param user to send Notifications to
	 */
	public synchronized void sendNotifications(User user)
	{
		List<String> notifications=new ArrayList<String>(user.getArrNotifications());
		user.getArrNotifications().clear();		
		for(String str:notifications)
		{
			this.sendUDPMessage(user, str);
		}
	}
	
	/**
	 * Logs a User out (his ClientAddress will be set to null),
	 * Clientaddress and Clientport to validate that the user was logged in at that Client
	 * (shouldn't be possible anyway)
	 * @param strName Usert to log out
	 * @param iaClientAddress InetAddress of client used by this User/Client
	 * @return User object or null if the user was not logged in at that Client
	 */	
	public synchronized User logout(String strName,InetAddress iaClientAddress,int iPClientPort)
	{
		User user=users.get(strName);
		if(user==null || user.getIAClientAddress()==null || !user.getIAClientAddress().equals(iaClientAddress) || user.getiPClientPort()!=iPClientPort)
		{
			return null;
		}
		else
		{
			user.setIAClientAddress(null);
			user.setiPClientPort(0);
		}
		return user;
	}
	
	/**
	 * Sends a UDP-Message to a User, the message is sent immediately if the user is online,
	 * otherwise it is added to arrNotifications and sent, when the User logs in
	 * @param user User to send a Message to
	 * @param message String Message to send
	 */
	public synchronized void sendUDPMessage(User user,String message)
	{
		if(user!=null)
		{
			try 
			{
				String strNotSent=UDPMessenger.getInstance().sendMessage(user.getIAClientAddress(), user.getiPClientPort(), message);
				if(strNotSent!=null)
				{
					user.getArrNotifications().add(strNotSent);
				}
			}
			catch (SocketException e) 
			{
				System.out.println("Error while sending '"+message+"' to '"+user+"'!");
				user.getArrNotifications().add(message);
			}
		}
	}
	
	
}
